package com.itheima.pinda.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.pinda.DTO.OrderDTO;
import com.itheima.pinda.DTO.OrderSearchDTO;
import com.itheima.pinda.common.utils.CustomIdGenerator;
import com.itheima.pinda.entity.AddressCheckResult;
import com.itheima.pinda.entity.AddressRule;
import com.itheima.pinda.entity.Order;
import com.itheima.pinda.entity.OrderCargo;
import com.itheima.pinda.enums.OrderPaymentStatus;
import com.itheima.pinda.enums.OrderPickupType;
import com.itheima.pinda.enums.OrderStatus;
import com.itheima.pinda.mapper.OrderCargoMapper;
import com.itheima.pinda.mapper.OrderMapper;
import com.itheima.pinda.service.IOrderService;
import com.itheima.pinda.utils.BaiDuApiUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;

/**
 * 订单服务实现类
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {
    @Autowired
    private CustomIdGenerator idGenerator;
    @Autowired
    private IOrderService orderService;
    @Autowired
    private KieContainer kieContainer;
    @Autowired
    private OrderCargoMapper orderCargoMapper;
    @Autowired
    private OrderMapper orderMapper;

    @Override
    public OrderDTO saveOrder(OrderDTO orderDTO) {

        Order order = new Order();
        BeanUtils.copyProperties(orderDTO,order);
        order.setId(idGenerator.nextId(order) + "");
        order.setCreateTime(LocalDateTime.now());
        order.setEstimatedArrivalTime(LocalDateTime.now().plus(2, ChronoUnit.DAYS));
        order.setPaymentStatus(OrderPaymentStatus.UNPAID.getStatus());
        if (OrderPickupType.NO_PICKUP.getCode() == order.getPickupType()) {
            order.setStatus(OrderStatus.OUTLETS_SINCE_SENT.getCode());
        } else {
            order.setStatus(OrderStatus.PENDING.getCode());
        }

        // 获取距离
        String lngLat1 = BaiDuApiUtils.getLngLat(order.getSenderAddress());
        String lngLat2 = BaiDuApiUtils.getLngLat(order.getReceiverAddress());
        String distance = BaiDuApiUtils.getDistance(lngLat1, lngLat2);

        order.setDistance(new BigDecimal(distance).divide(new BigDecimal(1000),0,BigDecimal.ROUND_HALF_UP));

        // 获取金额
        BigDecimal amount = orderService.calculateAmount(order.getDistance().toString(), orderDTO.getOrderCargoDto().getTotalWeight());

        if (ObjectUtils.isEmpty(amount)) {
            throw new RuntimeException("运费获取失败，请检查！");
        }
        order.setAmount(amount);
        orderMapper.insert(order);

        BeanUtils.copyProperties(order, orderDTO);

        // 插入货物信息
        OrderCargo orderCargo = new OrderCargo();
        BeanUtils.copyProperties(orderDTO.getOrderCargoDto(), orderCargo);
        orderCargo.setOrderId(idGenerator.nextId(orderCargo) + "");
        orderCargoMapper.insert(orderCargo);
        orderDTO.getOrderCargoDto().setOrderId(orderCargo.getOrderId());

        return orderDTO;
    }

    @Override
    public IPage<Order> findByPage(Integer page, Integer pageSize, Order order) {
        Page<Order> iPage = new Page(page, pageSize);
        LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(order.getId())) {
            lambdaQueryWrapper.like(Order::getId, order.getId());
        }
        if (order.getStatus() != null) {
            lambdaQueryWrapper.eq(Order::getStatus, order.getStatus());
        }
        if (order.getPaymentStatus() != null) {
            lambdaQueryWrapper.eq(Order::getPaymentStatus, order.getPaymentStatus());
        }
        //发件人信息
        if (StringUtils.isNotEmpty(order.getSenderName())) {
            lambdaQueryWrapper.like(Order::getSenderName, order.getSenderName());
        }
        if (StringUtils.isNotEmpty(order.getSenderPhone())) {
            lambdaQueryWrapper.like(Order::getSenderPhone, order.getSenderPhone());
        }
        if (StringUtils.isNotEmpty(order.getSenderProvinceId())) {
            lambdaQueryWrapper.eq(Order::getSenderProvinceId, order.getSenderProvinceId());
        }
        if (StringUtils.isNotEmpty(order.getSenderCityId())) {
            lambdaQueryWrapper.eq(Order::getSenderCityId, order.getSenderCityId());
        }
        if (StringUtils.isNotEmpty(order.getSenderCountyId())) {
            lambdaQueryWrapper.eq(Order::getSenderCountyId, order.getSenderCountyId());
        }
        //收件人信息
        if (StringUtils.isNotEmpty(order.getReceiverName())) {
            lambdaQueryWrapper.like(Order::getReceiverName, order.getReceiverName());
        }
        if (StringUtils.isNotEmpty(order.getReceiverPhone())) {
            lambdaQueryWrapper.like(Order::getReceiverPhone, order.getReceiverPhone());
        }
        if (StringUtils.isNotEmpty(order.getReceiverProvinceId())) {
            lambdaQueryWrapper.eq(Order::getReceiverProvinceId, order.getReceiverProvinceId());
        }
        if (StringUtils.isNotEmpty(order.getReceiverCityId())) {
            lambdaQueryWrapper.eq(Order::getReceiverCityId, order.getReceiverCityId());
        }
        if (StringUtils.isNotEmpty(order.getReceiverCountyId())) {
            lambdaQueryWrapper.eq(Order::getReceiverCountyId, order.getReceiverCountyId());
        }
        lambdaQueryWrapper.orderBy(true, false, Order::getId);
        return page(iPage, lambdaQueryWrapper);
    }

    @Override
    public List<Order> findAll(List<String> ids) {
        LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (ids != null && ids.size() > 0) {
            lambdaQueryWrapper.in(Order::getId, ids);
        }
        lambdaQueryWrapper.orderBy(true, false, Order::getId);
        return list(lambdaQueryWrapper);
    }

    @Override
    public IPage<Order> pageLikeForCustomer(OrderSearchDTO orderSearchDTO) {

        Integer page = orderSearchDTO.getPage();
        Integer pageSize = orderSearchDTO.getPageSize();

        IPage<Order> ipage = new Page<>(page, pageSize);

        LambdaQueryWrapper<Order> orderQueryWrapper = new LambdaQueryWrapper<>();
        orderQueryWrapper.eq(StringUtils.isNotEmpty(orderSearchDTO.getId()), Order::getId, orderSearchDTO.getId());
        orderQueryWrapper.like(StringUtils.isNotEmpty(orderSearchDTO.getKeyword()), Order::getId, orderSearchDTO.getKeyword());
        orderQueryWrapper.eq(StringUtils.isNotEmpty(orderSearchDTO.getMemberId()), Order::getMemberId, orderSearchDTO.getMemberId());
        orderQueryWrapper.eq(StringUtils.isNotEmpty(orderSearchDTO.getReceiverPhone()), Order::getReceiverPhone, orderSearchDTO.getReceiverPhone());
        orderQueryWrapper.orderByDesc(Order::getCreateTime);
        return page(ipage, orderQueryWrapper);
    }



    /**
     * 计算订单价格
     * @param distance
     * @param totalWeight
     * @return
     */
    public BigDecimal calculateAmount(String distance, BigDecimal totalWeight) {

        // 调用规则引擎
        KieSession session = kieContainer.newKieSession();

        AddressRule addressRule = new AddressRule();
        addressRule.setDistance(new Double(distance));
        addressRule.setTotalWeight(totalWeight.doubleValue());

        AddressCheckResult addressCheckResult = new AddressCheckResult();

        // 将对象加入到工作内存中
        session.insert(addressRule);
        session.insert(addressCheckResult);

        session.fireAllRules();
        session.destroy();


        if (addressCheckResult.isPostCodeResult()) {
            return new BigDecimal(addressCheckResult.getResult());
        }

        return null;
    }

    /**
     * 调用百度地图服务接口，根据寄件人地址和收件人地址计算订单距离
     * @param orderDTO
     * @return
     */
    public OrderDTO getDistance(OrderDTO orderDTO){
        //调用百度地图服务接口获取寄件人地址对应的坐标经纬度
        return null;
    }
}
